import { Inject, Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { REST_URL } from '../app.component';
import { URLConst } from '../consts/url-const';
import { ApiResult } from '../models/api.result';
import { AddClientParam } from '../models/param/add-client.param';
import { AddDeptParam } from '../models/param/add-dept.param';
import { ClientQueryParam } from '../models/param/client-query.param';
import { DeptQueryParam } from '../models/param/dept-query.param';
import { IntIdParam } from '../models/param/int-id.param';
import { MenuQueryParam } from '../models/param/menu-query.param';
import { RoleQueryParam } from '../models/param/role-query.param';
import { RoleUserQueryParam } from '../models/param/role-user-query.param';
import { UserQueryParam } from '../models/param/user-query.param';
import { ClientMenuDto } from '../models/sys/client-menu.dto';
import { ClientDto } from '../models/sys/client.dto';
import { DeptDto } from '../models/sys/dept.dto';
import { MenuDto } from '../models/sys/menu.dto';
import { RoleMenuDto } from '../models/sys/role-menu.dto';
import { RoleDto } from '../models/sys/role.dto';
import { UserDto } from '../models/sys/user.dto';
import { HttpService } from './http.service';
import { AddRoleParam } from '../models/param/add-role.param';
import { DictDto } from '../models/sys/dict.dto';
import { AddMenuParam } from '../models/param/add-menu.param';
import { AddUserParam } from '../models/param/add-user.param';
import { UpdateUserParam } from '../models/param/update-user.param';
import { UserPassword } from '../models/bo/user-password';
import { UserPermParam } from '../models/param/user-perm.param';
import { UpdateRoleParam } from '../models/param/update-role.param';
import { UpdateClientParam } from '../models/param/update-client.param';
import { UpdateMenuParam } from '../models/param/update-menu.param';
import { UpdateDeptParam } from '../models/param/update-dept.param';
import { RoleDataScopeParam } from '../models/param/role-data-scope.param';
import { EndUserQueryParam } from '../models/param/end-user-query.param';
import { EndUserDto } from '../models/sys/end-user.dto';
import { ClientMenuQueryParam } from '../models/param/client-menu-query.param';
import { GroupQueryParam } from '../models/param/group-query.param';
import { GroupDto } from '../models/sys/group.dto';
import { AddGroupTypeParam } from '../models/param/add-group-type.param';
import { AddGroupParam } from '../models/param/add-group.param';
import { PageParam } from '../models/param/page.param';
import { UpdateGroupTypeParam } from '../models/param/update-group-type.param';
import { UserInfoDto } from '../models/sys/user-info.dto';
import { GroupTypeDto } from '../models/sys/group-type.dto';
import { PostQueryParam } from '../models/param/post-query.param';
import { PostDto } from '../models/sys/post.dto';
import { AddPostParam } from '../models/param/add-post.param';
import { UpdatePostParam } from '../models/param/update-post.param';
import { AddDeptTypeParam } from '../models/param/add-dept-type.param';
import { UpdateDeptTypeParam } from '../models/param/update-dept-type.param';
import { DeptTypeDto } from '../models/sys/dept-type.dto';

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  constructor(private httpService: HttpService,
    @Inject(REST_URL) private baseUrl: string) { }

  logout(): Observable<object> {
    const url = this.baseUrl + URLConst.LOGOUT_URL;
    return this.httpService.get(url);
  }

  // Menu
  getMenuTree(param?: MenuQueryParam): Observable<ApiResult<MenuDto[]>> {
    const url = this.baseUrl + URLConst.MENU_TREE;
    if (param == null) {
      return this.httpService.get<ApiResult<MenuDto[]>>(url);
    } else {
      console.log(`ready to get menu tree : ${url}`);
      return this.httpService.getWithParam<ApiResult<MenuDto[]>>(url, param);
    }
  }

  getMenuTreePage(param?: MenuQueryParam): Observable<ApiResult<MenuDto[]>> {
    const url = this.baseUrl + URLConst.MENU_TREE_PAGE;
    if (param == null) {
      return this.httpService.get<ApiResult<MenuDto[]>>(url);
    } else {
      console.log(`ready to get menu tree page : ${url}`);
      return this.httpService.getWithParam<ApiResult<MenuDto[]>>(url, param);
    }
  }

  getClientMenuTree(param: MenuQueryParam): Observable<ApiResult<MenuDto[]>> {
    const url = this.baseUrl + URLConst.CLIENT_MENU_TREE;
    return this.httpService.getWithParam(url, param);
  }

  getRoleMenu(param: IntIdParam): Observable<ApiResult<RoleMenuDto[]>> {
    const url = this.baseUrl + URLConst.ROLE_MENU;
    return this.httpService.getWithParam(url, param);
  }

  getClientMenu(param: ClientMenuQueryParam): Observable<ApiResult<ClientMenuDto[]>> {
    const url = this.baseUrl + URLConst.CLIENT_MENU;
    return this.httpService.getWithParam(url, param);
  }

  addMenu(param: AddMenuParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.MENU_PATH;
    return this.httpService.post(url, param);
  }

  deleteMenu(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.MENU_PATH + "/" + id;
    return this.httpService.delete(url);
  }

  updateMenu(param: UpdateMenuParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.MENU_PATH;
    return this.httpService.putWithBody(url, param);
  }

  // Clients
  getClientList(param: ClientQueryParam): Observable<ApiResult<ClientDto[]>> {
    const url = this.baseUrl + URLConst.CLIENT_LIST;
    return this.httpService.getWithParam(url, param);
  }

  addClient(param: AddClientParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.CLIENT_PATH;
    return this.httpService.post(url, param);
  }

  deleteClient(id: string): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.CLIENT_PATH + "?id=" + id;
    return this.httpService.delete(url);
  }

  updateClient(param: UpdateClientParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.CLIENT_PATH;
    return this.httpService.putWithBody(url, param);
  }

  // Roles
  getRoleList(param: RoleQueryParam): Observable<ApiResult<RoleDto[]>> {
    const url = this.baseUrl + URLConst.ROLE_LIST;
    return this.httpService.getWithParam(url, param);
  }

  getRoleDetail(roleId: number): Observable<ApiResult<RoleDto>> {
    const url = this.baseUrl + URLConst.ROLE_PATH + "/" + roleId;
    return this.httpService.get(url);
  }

  addRole(param: AddRoleParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.ROLE_PATH;
    return this.httpService.post(url, param);
  }

  updateRole(param: UpdateRoleParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.ROLE_PATH;
    return this.httpService.putWithBody(url, param);
  }

  updateAuthDataScope(param: RoleDataScopeParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.ROLE_DATA_SCOPE;
    return this.httpService.putWithBody(url, param);
  }

  deleteRole(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.ROLE_PATH + "/" + id;
    return this.httpService.delete(url);
  }

  // Employee
  getUserList(param: UserQueryParam): Observable<ApiResult<UserDto[]>> {
    const url = this.baseUrl + URLConst.USER_LIST;
    return this.httpService.getWithParam(url, param);
  }

  getUserDetail(userId: number): Observable<ApiResult<UserDto>> {
    const url = this.baseUrl + URLConst.USER_PATH + "/" + userId;
    return this.httpService.get(url);
  }

  getUsersByRole(param: RoleUserQueryParam): Observable<ApiResult<UserDto[]>> {
    const url = this.baseUrl + URLConst.USER_BY_ROLE;
    return this.httpService.getWithParam(url, param);
  }

  getUserInfo(): Observable<ApiResult<UserInfoDto>> {
    const url = this.baseUrl + URLConst.USER_INFO;
    return this.httpService.get(url);
  }

  addUser(param: AddUserParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.USER_PATH;
    return this.httpService.post(url, param);
  }

  updateUser(param: UpdateUserParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.USER_PATH;
    return this.httpService.putWithBody(url, param);
  }

  resetUserPassword(param: UserPassword): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.RESET_PASSWORD;
    return this.httpService.putWithBody(url, param);
  }

  assignRoles(param: UserPermParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.USER_ASSIGN_ROLES;
    return this.httpService.putWithBody(url, param);
  }

  deleteUser(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.USER_PATH + "/";
    return this.httpService.deleteByIds(url, [id]);
  }

  // EndUser
  getEndUserList(param: EndUserQueryParam): Observable<ApiResult<EndUserDto[]>> {
    const url = this.baseUrl + URLConst.END_USER_LIST;
    return this.httpService.getWithParam(url, param);
  }

  // Depts
  getDeptTree(param: DeptQueryParam): Observable<ApiResult<DeptDto[]>> {
    const url = this.baseUrl + URLConst.DEPT_TREE;
    return this.httpService.getWithParam(url, param);
  }

  addDept(param: AddDeptParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.DEPT_PATH;
    return this.httpService.post(url, param);
  }

  updateDept(param: UpdateDeptParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.DEPT_PATH;
    return this.httpService.putWithBody(url, param);
  }

  deleteDept(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.DEPT_PATH + "/" + id;
    return this.httpService.delete(url);
  }

  getDeptTypeList(param: PageParam): Observable<ApiResult<DictDto[]>> {
    const url = this.baseUrl + URLConst.DEPTP_TYPES;
    return this.httpService.getWithParam(url, param);
  }

  deleteDeptType(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.GROUP_TYPE + "/" + id;
    return this.httpService.delete(url);
  }

  addDeptType(param: AddDeptTypeParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.DEPT_TYPE;
    return this.httpService.post(url, param);
  }

  updateDeptType(param: UpdateDeptTypeParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.DEPT_TYPE;
    return this.httpService.putWithBody(url, param);
  }

  getDeptTypeDetail(typeId: number): Observable<ApiResult<DeptTypeDto>> {
    const url = this.baseUrl + URLConst.DEPT_TYPE + "/" + typeId;
    return this.httpService.get(url);
  }

  // Types
  getMenuType(): Observable<ApiResult<DictDto[]>> {
    const url = this.baseUrl + URLConst.ENUM_MENU_TYPE;
    return this.httpService.get(url);
  }

  getSexType(): Observable<ApiResult<DictDto[]>> {
    const url = this.baseUrl + URLConst.ENUM_SEX;
    return this.httpService.get(url);
  }

  getDataScopes(): Observable<ApiResult<DictDto[]>> {
    const url = this.baseUrl + URLConst.ENUM_DATA_SCOPE;
    return this.httpService.get(url);
  }

  // Group
  getGroupList(param: GroupQueryParam): Observable<ApiResult<GroupDto[]>> {
    const url = this.baseUrl + URLConst.GROUP_LIST;
    return this.httpService.getWithParam(url, param);
  }

  getGroupsByRole(param: IntIdParam): Observable<ApiResult<GroupDto[]>> {
    const url = this.baseUrl + URLConst.GROUP_BY_ROLE;
    return this.httpService.getWithParam(url, param);
  }

  addGroupType(param: AddGroupTypeParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.GROUP_TYPE;
    return this.httpService.post(url, param);
  }

  getGroupTypeDetail(typeId: number): Observable<ApiResult<GroupTypeDto>> {
    const url = this.baseUrl + URLConst.GROUP_TYPE + "/" + typeId;
    return this.httpService.get(url);
  }

  updateGroupType(param: UpdateGroupTypeParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.GROUP_TYPE;
    return this.httpService.putWithBody(url, param);
  }

  deleteGroupType(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.GROUP_TYPE + "/" + id;
    return this.httpService.delete(url);
  }

  deleteGroup(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.GROUP_PATH + "/" + id;
    return this.httpService.delete(url);
  }

  addGroup(param: AddGroupParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.GROUP_PATH;
    return this.httpService.post(url, param);
  }

  getGroupTypeList(param: PageParam): Observable<ApiResult<DictDto[]>> {
    const url = this.baseUrl + URLConst.GROUP_TYPES;
    return this.httpService.getWithParam(url, param);
  }

  // Post
  getPostList(param: PostQueryParam): Observable<ApiResult<PostDto[]>> {
    const url = this.baseUrl + URLConst.POST_LIST;
    return this.httpService.getWithParam(url, param);
  }

  addPost(param: AddPostParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.POST_PATH;
    return this.httpService.post(url, param);
  }

  updatePost(param: UpdatePostParam): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.POST_PATH;
    return this.httpService.putWithBody(url, param);
  }

  deletePost(id: number): Observable<ApiResult<boolean>> {
    const url = this.baseUrl + URLConst.POST_PATH + "/" + id;
    return this.httpService.delete(url);
  }
}
